
#ifndef __FIREWIRE_H__
#define __FIREWIRE_H__

// The following ifdef block is the standard way of creating macros which 
// make exporting from a DLL simpler. All files within this DLL are compiled 
// with the FIREWIRE_EXPORTS symbol defined on the command line. this symbol 
// should not be defined on any project that uses this DLL. This way any 
// other project whose source files include this file see FIREWIRE_API_2 
// functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
//
// To make this dll conform to C calling conventions instead of stdcall, 
// remove __stdcall from FIREWIRE_API_2 and recompile the DLL and all 
// programs that rely on it.
#ifdef FIREWIRE_EXPORTS
#define FIREWIRE_API_1 __declspec(dllexport)
#define FIREWIRE_API_2 __stdcall
#else
#define FIREWIRE_API_1 __declspec(dllimport)
#define FIREWIRE_API_2 __stdcall
#endif

/// Function completed successfully.
#define VHPD_SUCCESS                0
/// Error while initializing, or initialization was not completed before this function was called.
#define VHPD_INIT_ERROR             -1
/// Error closing the unit.
#define VHPD_CLOSE_ERROR            -2
/// Error opening
#define VHPD_OPEN_ERROR             -3
/// Error reading
#define VHPD_READ_ERROR	            -4
/// Error writing
#define VHPD_WRITE_ERROR            -5
/// There is an error in the configuration.
#define VHPD_CONFIG_ERROR           -6
/// The reference passed to the function was invalid.
#define VHPD_BAD_REFERENCE          -7
/// A bad parameter was passed.
#define VHPD_BAD_PARAM              -8
/// This functionality is not implemented.
#define VHPD_NOT_IMPLEMENTED        -9
/// There is not enough memory available to perform the operation.
#define VHPD_OUT_OF_MEMORY          -10
/// There are no devices remaining.
#define VHPD_NO_DEVICES             -11
/// The buffer passed in was too small.
#define VHPD_BUFFER_TOO_SMALL		-12
/// There is no data available. This is not necessarily an error.
#define VHPD_NO_DATA_AVAILABLE		-13
/// The thread is already running.
#define VHPD_ALREADY_RUNNING		-14
/// Timeout processing request.
#define VHPD_TIMEOUT                -15


typedef int SInt32;
typedef unsigned int UInt32;

#define VHPD_VERSION "v01.80.00 2011-01-01" 

////
// Definitions that are internal to the DLL
////
#ifdef FIREWIRE_EXPORTS

#include <CVhpd.h>
#include <CVhpdBuf.h>
#include <CVhpdNotifySlave.h>
#include <queue>

using namespace std;

class VhpdBuffer;
class CIsoToFile;

typedef struct {
    UInt32 device;
    UInt32 node;
    UInt32 vendorId;
    UInt32 chipIdHigh;
    UInt32 chipIdLow;
} VhpdScanResult;

typedef struct {
    CVhpd vhpd;
    int deviceNumber;
    HDEVINFO devList;
    DWORD resetGenerationCount;
	CVhpdNotifySlave* notifySlave;
	CVhpdBuf* buffer;
	CIsoToFile* isoToFile;
	int isochronousThreadRunning;
	int numberOfBuffers;
    int threadRunning;

    //  TBD:  This is a temporary test.
	queue<VhpdBuffer*> dataQueue;
    HANDLE  dataQueueEvent;

    /// Stores the result of a scan. These values can be retrieved with
    /// the VHPDscanDeviceInfo* commands.
    VhpdScanResult scanResult[64];
} VhpdReferenceStruct;

typedef VhpdReferenceStruct* VhpdReference;

#else

typedef void* VhpdReference;

#endif

#ifdef __cplusplus
extern "C" {
#endif

/**************************************************************************//**
* \brief   A dummy function used to make sure the dll is linked in properly and
*          that everything is functioning. 
*
* \param   a a value to add
* \param   b a value to add.
*
* \return  sum of a and b
*******************************************************************************/ 
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 addTwoNumbers(int a, int b);

/**************************************************************************//**
* \brief   Close the driver. This function must be called when you are done 
*          using the specific device. This function will close down all 
*          resources, free any allocated memory and stop any threads. If 
*          this method is not called then Windows may not allow you to 
*         'safely remove' the hardware.
* \param   vhpdReference The reference as created by VHPDinit
*
* \return  VHPD_CLOSE_ERROR if the device could not be stopped
* \return  VHPD_SUCCESS on success
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDclose(VhpdReference vhpdReference);

/**************************************************************************//**
* \brief   This function will retrieve a block of memory that has been written
*          to the block of memory allocated by VHPDsetupWriteBuffer.
*
* \param   vhpdReference The reference as created by VHPDinit
* \param   str The buffer that VHPDgetQueuedBlock will put data into.
* \param   strLength This is the size (in bytes) of the buffer 'str' that 
*          was passed in this should be at least one greater than the 
*          bufferSize passed into VHPDsetupWriteBuffer.
*
* \return  VHPD_BUFFER_TOO_SMALL if data size is greater than \c strLength
* \return  VHPD_NO_DATA_AVAILABLE if the data queue is empty
* \return  VHPD_SUCCESS on success
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDgetQueuedBlock(
    VhpdReference vhpdReference, char* str, UInt32 strLength);

/**************************************************************************//**
* \brief   This function will retrieve a response, terminated by a newline. The
*          data is retrieved by memory allocated by VHPDsetupWriteBuffer.
*
* \param   vhpdReference The reference as created by VHPDinit
* \param   resp The buffer where the response is built.  The result is
*          NULL terminated with a newline near the end.
* \param   respSize The size (in bytes) of the resp.
* \param   timeoutMs The timeout in milliseconds for building the response.
*
* \return  VHPD_BAD_PARAM if response size is zero.
* \return  VHPD_TIMEOUT if no data was available or request timed out.
* \return  VHPD_BUFFER_TOO_SMALL if response buffer is too small.
* \return  VHPD_SUCCESS on success.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDgetQueuedResponse (
    VhpdReference vhpdReference,
	char*         resp, 
    UInt32        respSize,
    SInt32        timeoutMs);

/**************************************************************************//**
* \brief   Get the version of the VHPD Driver
*
* \return  Returns a string describing the version of the software.
******************************************************************************/
FIREWIRE_API_1 const char* FIREWIRE_API_2 VHPDgetVersion();

/**************************************************************************//**
* \brief   Initialize the firewire drivers.
*
* \param   vhpdReference The reference to this instantiation of VHPD. This
*          should be passed into each function. If you are using a non-c based
*          language you can just pass in a pointer to a 32bit value or 
*          pass a 32bit value 'by reference'.
*
* \return  VHPD_OUT_OF_MEMORY if memory wasn't allocated
* \return  VHPD_INIT_ERROR if the reference wasn't created
* \return  VHPD_SUCCESS on success
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDinit(VhpdReference *vhpdReference);

/**************************************************************************//**
* \brief   Get buffered data from an isochronous transfer.
*
* \param   vhpdReference The reference as created by VHPDinit
* \param   size The size of the data buffer (in bytes) that we're 
*          transfering data into. At this point this data buffer should be no 
*          smaller than 65536.
* \param   data A pointer to the block of memory that we'll be copying data
*          into.
* \param   timeout The time in milliseconds that we should wait for data. 
*          0 will return immediately, -1 will pause indefinately.
*
* \return  VHPD_NO_DATA_AVAILABLE If there is no data available and the
*          timeout elapsed.
* \return  VHPD_BUFFER_TOO_SMALL If the buffer passed in is too small.
* \return  VHPD_CONFIG_ERROR If this command was called out of sequence and
*          we aren't in a configuration for retrieving data.
* \return  VHPD_SUCCESS on success.
* \return  Number of bytes transfered if the transfer was successful and 
*          data was placed into 'data'.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDisochronousGetData(
    VhpdReference vhpdReference, UInt32 size, char* data, SInt32 timeout);

/**************************************************************************//**
* \brief   Returns the number of Isochronous bytes queued and ready for read
*          by VHPDisochronousGetData.
*
* \param   vhpdReference The reference as created by VHPDinit
*
* \return  number of bytes queued.
******************************************************************************/
FIREWIRE_API_1 UInt32 FIREWIRE_API_2 VHPDisochronousBytesQueued(
    VhpdReference vhpdReference);

/**************************************************************************//**
* \brief   Isochronous Receive Overrun Stats
*
* \param   vhpdReference The reference as created by VHPDinit
* \param   p_BytesLost is address of UInt32 variable to contain the number
*          of bytes LOST due to overrun.  NULL if no update needed.
* \param   p_DriverOverrunCount is address of UInt32 variable to contain the
*          number of times the driver has been overrun.  This is separate
*          from the "p_BytesLost" which is APPLICATION overrun (i.e., user
*          application not reading the data quick enough).
* \param   resetStats TRUE indicates that the current stats should be zeroed.
*
* \return  number of overrun occurrences.
******************************************************************************/
FIREWIRE_API_1 UInt32 FIREWIRE_API_2 VHPDisochronousOverrunStats(
    VhpdReference  vhpdReference, 
    UInt32        *p_BytesLost, 
    UInt32        *p_DriverOverrunCount,
    BOOL           resetStats);

/**************************************************************************//**
* \brief   Initialize an isochronous transfer. To start the transfer 
*          you must call VHPDisochronousStart.
*
* \param   vhpdReference The reference as created by VHPDinit
* \param   channel The isochronous channel to use.
* \param   bandwidth The estimated bandwidth of the channel. The bandwidth
*          must be greater than 32000.
* \param   framesPerBuffer The number of frames per buffer per transfer. A 
*          good size to use is 256, for small transfers framesPerBuffer should
*          be set to (transfer size / 2048 bytes) otherwise you won't receive 
*          any data back. You might noticed dropped packets if this value is 
*          set too small.
* \param   fileName The filename to stream data to. If this is set to 0 or
*          "", then no data will be streamed to a file and the data can be
*          retrieved via VHPDisochronousGetData. This buffered data will never
*          use more than fileSize memory to buffer the data.
* \param   fileSize The maximum fileSize (in bytes) to write out if the
*          fileSize is < 0 then there is no limit on the file size. Note: this
*          has not been tested for file sizes greater then the OS supports and
*          the operation is undefined in these cases.
*
* \return  VHPD_BAD_PARAM if bandwidth < 32000 or cannot open file.
* \return  VHPD_ALREADY_RUNNING if it is already running.
* \return  VHPD_CONFIG_ERROR if the iso channel could not be set up.
* \return  VHPD_SUCCESS on success.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDisochronousInit(
    VhpdReference vhpdReference, UInt32 channel, UInt32 bandwidth, 
	UInt32 framesPerBuffer, const char* fileName, int fileSize);

/**************************************************************************//**
* \brief   Pause the isochronous transfer.
*
* \param   vhpdReference The reference as created by VHPDinit
*
* \return  VHPD_CLOSE_ERROR if the thread cannot shutdown.
* \return  VHPD_SUCCESS on success.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDisochronousPause(
    VhpdReference vhpdReference);

/**************************************************************************//**
* \brief   Start the isochronous transfer. This can be called after pause to 
*          continue the transfer again.
*
* \param   vhpdReference The reference as created by VHPDinit
*
* \return  VHPD_ALREADY_RUNNING if the thread is already running.
* \return  VHPD_CONFIG_ERROR if the thread failed to start.
* \return  VHPD_SUCCESS on success.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDisochronousStart(
    VhpdReference vhpdReference);

/**************************************************************************//**
* \brief   Stop the isochronous transfer. If you want to start another transfer 
*          again, you must call VHPDisochronousInit.
*
* \param   vhpdReference The reference as created by VHPDinit
*
* \return  VHPD_SUCCESS on success.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDisochronousStop(
    VhpdReference vhpdReference);

/**************************************************************************//**
* \brief   Open a specific device for communication. This is the only device 
*          that will be used for this specific reference.
*
* \param   vhpdReference The reference as created by VHPDinit.
* \param   deviceIndex The index of the device to open.
*
* \return  VHPD_NO_DEVICES if no devices are present.
* \return  VHPD_OPEN_ERROR if the device failed to open.
* \return  VHPD_SUCCESS on success.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDopen(VhpdReference vhpdReference, 
    UInt32 deviceIndex);

/**************************************************************************//**
* \brief   Read a block of data from a specific address on the firewire bus. 
*
* \param   vhpdReference The reference as created by VHPDinit
* \param   highAddress The upper 4 bytes of the start address for transfer.
* \param   lowAddress The lower 4 bytes of the start address for transfer.
* \param   str The buffer to put the transfered data into.
* \param   strLength The size of the buffer and the amount of data to read.
*
* \note    Due to no way of testing, this function has never been tested.
*
* \return  VHPD_SUCCESS on success
* \return  VHPD_READ_ERROR on AsyncReadSync failure
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDreadBlock(
    VhpdReference vhpdReference, UInt32 highAddress, UInt32 lowAddress, 
    char* str, UInt32 strLength);

/**************************************************************************//**
* \brief  Calling this function will retrieve the information gathered by 
*         VHPDscanDevices. VHPDscanDevices should be called before this function
*         If any of these pointers is zero then a value will not be assigned.
*
* \param  vhpdReference The reference as created by VHPDinit
* \param  deviceIndex The index at which the device resides
* \param  device The device number.
* \param  node The node.
* \param  vendorId The vendor ID.
* \param  chipIdHigh The high word of the chip ID. Only the bottom 8 bits
*         are relevant.
* \param  chipIdLow The low word of the chip ID.
*
* \return VHPD_BAD_PARAM if device index is greater or equal to 63.
* \return VHPD_NO_DEVICES if there are no valid devices.
* \return VHPD_SUCCESS on success.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDscanDeviceInfo(
	VhpdReference vhpdReference, UInt32 deviceIndex, UInt32* device,
	UInt32* node, UInt32* vendorId, UInt32* chipIdHigh, UInt32* chipIdLow);

/**************************************************************************//**
* \brief   Calling this function will scan the bus for all devices and put
*          the number of devices on the bus into numberOfDevices. 
*
* \param   vhpdReference The reference as created by VHPDinit
* \param   numberOfDevices Pointer to the location the number of devices 
*          should be put in. 
*
* \note    *numberOfDevices will never be greater than 62.
*
* \return  VHPD_SUCCESS on success
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDscanDevices(
	VhpdReference vhpdReference, UInt32* numberOfDevices);

/**************************************************************************//**
* \brief   This function broadcasts the given quadlet as a PHY configuration 
*          packet on the firewire bus. No transformations (i.e. byte swapping) 
*          are performed on the packet before it is handed to the Thesycon 
*          drivers to be broadcast. 
*
* \param   vhpdReference The reference as created by VHPDinit
* \param   quadlet The PHY Configuration quadlet to be broadcast on the
*          firewire bus.
*
* \return  VHPD_SUCCESS on success 
* \return  VHPD_WRITE_ERROR if there was an error while trying
*          to write the PHY Configuration packet to the bus.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDsendPhysicalConfigPacket(
    VhpdReference vhpdReference, UInt32 quadlet);

/**************************************************************************//**
* \brief   This function configures a debug file for output while the DLL 
*          is running. This is intended for factory use only, but 
*          may provide some useful, but unsupported output to end users. 
*          When debugging is enabled all instances of the DLL on one 
*          machine will write to a single file and it will be enabled or 
*          disabled for all DLLs.
*
* \param   filename The name of the file to output to. If this value is 0
*		   then the currently opened file will be closed and no more output 
*		   will be produced.
*
* \return  VHPD_OPEN_ERROR If there was an error while trying 
*          to open the file.
* \return  VHPD_CLOSE_ERROR If there was an error while trying to close the
*		   file.
* \return  VHPD_SUCCESS on success.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDsetDebugFile(
    const char* filename);

/**************************************************************************//**
* \note    Undocumented internal function.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDsetIsoNumberOfBuffers(
    VhpdReference vhpdReference, int numberOfBuffers);

/**************************************************************************//**
* \brief   This function configures a write buffer for the firewire device 
*          to write to. This function will create a buffer full of memory, 
*		   hand it off to the device driver, and start a thread to monitor 
*		   the memory for writes. When a new write comes in the thread 
*		   will copy the new data and place it on a queue for retrieval 
*		   via VHPDgetQueuedBlock. This function must be called before 
*		   VHPDgetQueuedBlock is called. Typically, this only needs to 
*		   be done once (when the interface is opened/initialized).
*
* \param   vhpdReference The reference as created by VHPDinit
* \param   highAddress The upper 4 bytes of the starting address where the
*          memory is shared.
* \param   lowAddress The lower 4 bytes of the starting address where the 
*          memory is shared.
* \param   bufferSize The size of the buffer (in bytes) to create.
*
* \return  VHPD_CONFIG_ERROR if there was a configuration error while trying
*          to configure the firewire device.
* \return  VHPD_SUCCESS on success.
******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDsetupWriteBuffer(
    VhpdReference vhpdReference, UInt32 highAddress, UInt32 lowAddress, 
    UInt32 bufferSize);

/**************************************************************************//**
* \brief   Write a block of data to a specific address on the firewire bus.
* 
* \param   vhpdReference The reference as created by VHPDinit
* \param   highAddress The upper 4 bytes of the address to write to.
* \param   lowAddress The lower 4 bytes of the address to write to.
* \param   str A pointer to an array of 1 byte characters to write out. This
*          array of characters does not have to be null terminated.
* \param   strLength The length of str in bytes.
*
* \return  VHPD_WRITE_ERROR on error.
* \return  VHPD_SUCCESS on success.
*******************************************************************************/
FIREWIRE_API_1 SInt32 FIREWIRE_API_2 VHPDwriteBlock(
    VhpdReference vhpdReference, UInt32 highAddress, UInt32 lowAddress, 
    char* str, UInt32 strLength);


#ifdef __cplusplus
}
#endif

#endif

